﻿#ifndef PFPOINTER_H
#define PFPOINTER_H

#include "basepointer.h"
#include <serialize/data.h>

class CommonPack;
class ChainManage;
/**
 * @brief The PFPointer class
 *  实际的pointer实现。
 */
class PFPointer : public BasePointer
{
public:
    PFPointer();
    ~PFPointer() override;
    // BasePointer interface
public:
    bool buildDataLink(const IPFiveTuple &args)  override;
    void init(const InitArgs &args) override;
    bool start(const StartArgs &args) override;
    bool stop(const StopArgs &args) override;
    void request(const RequestPacket &pack) override;
    void reply(const ReplyPacket &pack) override;
    void ready() override;
    void disConnect(bool bCmd) override;
    void close(bool bCmd) override;

private:
    /**
     * @brief doCommonPack 处理公共数据包。
     * @param srcPack
     */
    void doCommonPack(const CommonPack &srcPack, bool bCmd);
    /**
     * @brief doStart 处理接收到的start指令。
     * @param content 指令内容。
     * @param bCmd 是否指令隧道。
     */
    void doStart(QByteArray content);
    /**
     * @brief doStop 处理接收到的stop指令。
     * @param content 指令内容。
     * @param bCmd 是否指令隧道。
     */
    void doStop(QByteArray content);
    /**
     * @brief doRequest 处理接收到的request指令。
     * @param content 指令内容。
     * @param bCmd 是否指令隧道。
     */
    void doRequest(QByteArray content);
    /**
     * @brief doReply 处理接收到的reply指令。
     * @param content 指令内容。
     * @param bCmd 是否指令隧道。
     */
    void doReply(QByteArray content);
    /**
     * @brief doReady 处理接收到的ready的指令。
     * @param content  指令内容。
     * @param bCmd 是否指令隧道。
     */
    void doReady(QByteArray content);
    /**
     * @brief packWrite 通用数据包写入数据
     * @param src 通用数据包，源数据。
     * @param dest 目的数据。
     */
    bool packWrite(int type, const QByteArray &src, QByteArray &dest);

    /**
     * @brief parserData 解析数据方法。
     * @tparam TData 数据实体类型。
     * @tparam TParser  数据实体解析器类型。
     * @param srcData  源数据。
     * @param dest 目的数据实体。
     */
    template<class TData, class TParser>
    bool parserData(const QByteArray &srcData, TData &destData)
    {
        TParser parser;
        Data src(srcData);
        if(parser.parse(src, destData) < 0)
        {
            return false;
        }
        return true;
    }
    /**
     * @brief writerData 数据编码方法。
     * @tparam TData 数据实体类型。
     * @tparam TWriter  数据实体编码器类型。
     * @param srcData  源数据实体。
     * @param destData 目的数据。
     * @param type 数据类型。
     */
    template<class TData, class TWriter>
    bool writerData(const TData &srcData, QByteArray &destData, int type)
    {
        TWriter writer;
        Data dest;
        bool writed = writer.write(srcData, dest);
        if(writed)
        {
            QByteArray packSrc = dest.buffer();
            writed = packWrite(type, packSrc, destData);
        }
        return writed;
    }
private:
    /**
     * @brief The InnerProc class
     *  链路数据接收处理类。
     */
    class InnerProc: public TunnelCallback
    {
    public:
        InnerProc(PFPointer *owner, bool bCmd);
        // TunnelCallback interface
    public:
        void onProc(const QByteArray &data) override;
        void onStateChange(bool state) override;
    private:
        PFPointer *m_owner;
        bool m_bCmd;
        QByteArray m_recvBuf; // 接收数据缓存。
    };
private:
    BaseTunnel *m_cmdTunnel;
    BaseTunnel *m_dataTunnel;
    InnerProc m_cmdProc; // 指令隧道的处理对象。
    InnerProc m_dataProc; // 数据隧道的处理对象。
    ChainManage *m_proceChain; // 处理责任链。
    friend class InnerProc;

};

#endif // PFPOINTER_H
